//
/**
 * Filename: fig10-29_reliable_sleep.c
 * Author:   csbonkers
 * Contact:  forever65535@qq.com
 * Date:     2021/6/20
 * Description:
 *    
 */

#include "apue.h"

static void sig_alrm(int signo) {
  /*
   * nothing to do, just returning wakes up sigsuspend()
   *
   */
}

unsigned int c_sleep(unsigned int seconds) {
  struct sigaction newact, oldact;
  newact.sa_handler = sig_alrm;
  sigemptyset(&newact.sa_mask);
  newact.sa_flags = 0;
  sigaction(SIGALRM, &newact, &oldact);
  //block SIGALRM ans save current signal mask
  sigset_t newmask, oldmask, suspmask;
  sigemptyset(&newmask);
  sigaddset(&newmask, SIGALRM);
  sigprocmask(SIG_BLOCK, &newmask, &oldmask);

  alarm(seconds);
  suspmask = oldmask;

  /* make sure SIGALRM isn't blocked */
  sigdelset(&suspmask, SIGALRM);

  // wait for any signal to be caught
  sigsuspend(&suspmask);

  /* some signal has been caught, SIGALRM is now blocked */

  unsigned int unslept = alarm(0);

  /*reset previous action*/
  sigaction(SIGALRM, &oldact, NULL);

  /* reset signal mask, which unblocks SIGALRM */
  sigprocmask(SIG_SETMASK, &oldmask, NULL);
  return unslept;
}

#include <time.h>
int main(int argc, char *argv[]) {
  //  c_sleep(10);
  struct timespec reqts, remts;
  reqts.tv_sec = 300;
  reqts.tv_nsec = 300000000;
  int ret = 0;
  if((ret =nanosleep(&reqts, &remts)) == -1){
    perror("nanosleep error");
  }
  return 0;
}